import { nextTick, reactive } from 'vue'
import { differenceInMinutes, format } from 'date-fns'
import { AfterTime, formatDate, typeOf } from '@/utils/cloud/utils'

export const uuid = hasHyphen => {
  const str = hasHyphen ? 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx' : 'xxxxxxxxxxxx4xxxyxxxxxxxxxxxxxxx'
  return str.replace(/[xy]/g, c => {
    const r = (Math.random() * 16) | 0
    const v = c === 'x' ? r : (r & 0x3) | 0x8
    return v.toString(16)
  })
}

export const initWH = dom => {
  const status = reactive({
    width: 0,
    height: 0
  })
  nextTick().then(() => {
    status.width = dom ? dom.clientWidth : 0
    status.height = dom ? dom.clientHeight : 0
  })
  return status
}

// param from参数
export const Filtration = (data, Library, isConversionUnits) => {
  const zidian = Library.value //字典
  var datas = {}
  let list = []
  if (data.time && data.time.length) {
    const { time, ...arry } = data
    if (arry.iot_id) {
      let { iot_id, ...data } = arry
      datas = data
    } else {
      datas = arry
    }
    let afterObject = DuplicateData(datas, Library) //求出来组合完成的值
    let maxVal = maxFunc(afterObject) //最大值和单位的集合数据
    let sameUnit = []
    for (let i in datas) {
      //循环折线图的数据
      let scale = zidian.scale_dict ? zidian.scale_dict[i] : 2
      let unit = zidian.unit_dict[i.toUpperCase()]
      let Mathabs = datas[i].map(item => Math.abs(item))
      let max
      try {
        maxVal.forEach(item => {
          //循环
          if (item.unit.includes(i)) {
            //如果在这个循环里边
            max = item.max //最大值就取最大值
            throw new Error('运行结束')
          } else {
            max = Math.max(...Mathabs)
          }
        })
      } catch (error) {}
      let oneunit = isConversionUnits === 0 ? unit : danweiHs(max, unit, '', scale).unit || ''
      if (sameUnit.includes(oneunit)) {
        let index = sameUnit.map(item => item).indexOf(oneunit) //获取数组的下表
        list.push({
          //单位
          name: `${zidian.key_dict[i.toUpperCase()] || ''}${oneunit ? '（' + oneunit + '）' : ''}`,
          yAxisIndex: index,
          valueName: i,
          data: datas[i].map((value, index) => {
            const res = isConversionUnits === 0 ? value : danweiHs(max, unit, value, scale).val
            //返回value
            return [
              time[index] && time[index].includes('.') ? time[index].split('.')[0] : time[index],
              typeof res === 'number' ? res.toFixed(2) : res
            ]
          })
        })
      } else {
        list.push({
          //单位
          name: `${zidian.key_dict[i.toUpperCase()] || ''}${oneunit ? '（' + oneunit + '）' : ''}`,
          yAxisIndex: sameUnit.length,
          valueName: i,
          data: datas[i].map((value, index) => {
            //返回value
            const res = isConversionUnits === 0 ? value : danweiHs(max, unit, value, scale).val
            return [
              time[index] && time[index].includes('.') ? time[index].split('.')[0] : time[index],
              typeof res === 'number' ? res.toFixed(2) : res
            ]
          })
        })
        sameUnit.push(oneunit)
      }
    }
  } else {
    let quert = ['time', 'iot_id']
    let keys = Object.keys(data).filter(item => {
      if (!quert.includes(item)) {
        return item
      }
    })
    if (!keys.length) {
      keys = Object.keys(zidian.key_dict)
    }
    // 提取相同基础单位的channel值到一起，获取最大值时使用
    let sameDefaultUnitData = {}
    keys.forEach(item => {
      const default_unit = zidian.unit_dict[item.toUpperCase()]
      if (sameDefaultUnitData[default_unit]) {
        sameDefaultUnitData[default_unit] = sameDefaultUnitData[default_unit].concat(data[item])
      } else {
        sameDefaultUnitData[default_unit] = data[item]
      }
    })
    keys.forEach(item => {
      let scale = zidian.scale_dict ? zidian.scale_dict[item.toUpperCase()] : 2
      let unit = zidian.unit_dict[item.toUpperCase()]
      let Mathabs = sameDefaultUnitData[unit] ? sameDefaultUnitData[unit].map(item => Math.abs(item)) : [0]
      let max = Math.max(...Mathabs)
      let oneunit = isConversionUnits === 0 ? unit : danweiHs(max, unit, '', scale).unit || ''
      list.push({
        name: `${zidian.key_dict[item.toUpperCase()] || ''}${oneunit ? '（' + oneunit + '）' : ''}`,
        valueName: item,
        data: data[item]
          ? data[item].map(value => {
              return isConversionUnits === 0 ? value : danweiHs(max, unit, value, scale).val
            })
          : []
      })
    })
  }
  return list
}

const Difference = date => {
  let datetime = []
  if (date && date.length) {
    datetime = date
  } else {
    datetime = [`${format(new Date(), 'yyyy-MM-dd')} 00:00:00`, `${format(new Date(), 'yyyy-MM-dd')} 23:59:59`]
  }
  // 时间间隔，用来求折线图的时间
  let start = formatDate(datetime[0])
  let end = formatDate(datetime[1])
  let second = differenceInMinutes(end, start)
  let time = (second * 60) / 1440
  return Math.ceil(time) //秒
}

export const danweiHs = (max = 0, unit, value = '', scale = 2) => {
  let unitObject = {}
  ;[
    ['mA', 'A'],
    ['mV', 'V'],
    ['mW', 'W', 'kW', 'MW', 'GW'],
    ['Wh', 'kWh', 'MWh', 'GWh'],
    ['Pa', 'kPa', 'MPa', 'GPa'],
    [
      {
        label: '分',
        value: 1
      },
      {
        label: '元',
        value: 100
      },
      {
        label: '万元',
        value: 10000
      }
    ]
  ].forEach(item => {
    item.forEach((element, key) => {
      let unitLabel = typeOf(element) === 'string' ? element : element.label
      unitObject[unitLabel] = item.slice(key + 1)
    })
  })
  if (!unitObject[unit]) {
    return {
      unit,
      val: value && !isNaN(value * 1) ? (value * 1).toFixed(scale) : value
      // - 0 ? value.toFixed(2) : value == 0 ? 0 : null
    }
  }
  let unitList = unitObject[unit] //确定单位列表
  let unitsss = unit //确定单位
  let index = 0 //通过它可以判断除以了多少10000，和单位
  let newvalue = Math.abs(max) //暂存数据求最大值
  //开始计算最大值
  //计算是正还是负
  let Pnegative = true
  if (value < 0) {
    Pnegative = false
  } else {
    Pnegative = true
  }
  const zidiao = val => {
    //
    if (val >= (unitList[index] && unitList[index].value ? unitList[index].value : 1000)) {
      //如果大于1000
      let unitLabel =
        typeOf(unitList[unitList.length - 1]) === 'string'
          ? unitList[unitList.length - 1]
          : unitList[unitList.length - 1].label
      if (unitsss != unitLabel) {
        //如果当前单位不等于最后一个单位
        newvalue = (val / (unitList[index].value || 1000)).toFixed(scale) //则值除以1000
        unitsss = typeOf(unitList[index]) === 'string' ? unitList[index] : unitList[index].label //单位往前取一个
        index++ //序列号加1
        zidiao(newvalue) //递归调用
      }
    } else {
      //如果单位在这个数组里边，则进行转换
      if (['mA', 'mV', 'mW'].includes(unitsss)) {
        unitsss = unitList[index] //单位往前取一个
        index++ //序列号加1
      }
    }
  }
  zidiao(newvalue)

  let values = value === null || value === '' ? null : Math.abs(value)

  if (index) {
    let powVal = 1 // unitList[index - 1] && unitList[index - 1].value ? 1 / unitList[index - 1].value : 0.001
    unitList.forEach((itm, ind) => {
      if (ind < index) {
        if (itm.value) {
          powVal *= 1 / itm.value
        } else {
          powVal *= 0.001
        }
      }
    })
    return {
      unit: unitsss,
      val:
        values === null || values === ''
          ? null
          : Pnegative
          ? (values * powVal).toFixed(scale)
          : -(values * powVal).toFixed(scale)
    }
  } else {
    return {
      unit: unitsss,
      val: values === null || values === '' ? null : Pnegative ? values.toFixed(scale) : -values.toFixed(scale)
    }
  }
}

export const quchong = (serves, data, param, msg_type) => {
  let step = Difference(param.date) //间隔秒

  // serves 目前已存在的数据
  if (msg_type == 'query') {
    return data
  }

  data.forEach((item, index) => {
    serves.forEach((element, sq) => {
      // item.valueName=element.valueName//如果新数据已存在
      if (item.valueName == element.valueName) {
        item.data.forEach(itemValue => {
          //新值的每个值
          for (let i = element.data.length - 1; i >= 0; i--) {
            //每个值循环
            //如果新进来数据的时间大于最后一个数据的时间，则直接跳出循环
            if (formatDate(itemValue[0]).getTime() > formatDate(element.data[i][0]).getTime()) {
              let s = (formatDate(itemValue[0]).getTime() - formatDate(element.data[i][0]).getTime()) / 1000
              if (s > step) {
                let Interval = Math.trunc(s / step) //求出间隔
                if (!Interval) return false
                for (let i = 0; i < Interval; i++) {
                  let time = AfterTime(element.data[i][0], 'S', step)
                  element.data.push([time, null])
                }
              }
              element.data.push(itemValue)
              return false
            } else {
              //如果小于或者等于
              if (element.data[i].includes(itemValue[0])) {
                //如果时间等于则直接进行替换
                element.data.splice(i, 1, itemValue)
                return false
              } else {
                //新进来的时间小于目前已存在的时间，则新进来的时候和原来的时间进行比较，如果原来时间小于新进来的时间，则在此处插入数据
                // itemValue//新进来的数据
                // element.data[i]//目前已有数据
                if (formatDate(element.data[i][0]).getTime() < formatDate(itemValue[0]).getTime()) {
                  //如果新进来的时间小于，则继续
                  element.data.splice(i + 1, 0, itemValue)
                  return false
                }
              }
            }
          }
        })
      }
    })
  })
  return serves
}

export const yAxismethod = (data, Library, theme, isConversionUnits, yAxisSource0, showYSplitLine = false) => {
  let list = []
  const zidian = Library.value
  const { time, iot_id, ...objs } = data
  let keys = Object.keys(Library.value.key_dict)
  let afterObject = DuplicateData(objs, Library) //求出来组合完成的值
  let maxVal = maxFunc(afterObject) //最大值和单位的集合数据
  if (Object.keys(objs).length) {
    for (let i in objs) {
      //循环折线图的数据
      let unit = zidian.unit_dict[i.toUpperCase()]
      let Mathabs = objs[i].map(item => Math.abs(item))
      let max
      try {
        maxVal.forEach(item => {
          //循环
          if (item.unit.includes(i)) {
            //如果在这个循环里边
            max = item.max //最大值就取最大值
            throw new Error('运行结束')
          } else {
            max = Math.max(...Mathabs)
          }
        })
      } catch (error) {}
      list.push({
        //单位
        name: `${isConversionUnits === 0 ? unit : danweiHs(max, unit).unit || ''}`,
        axisLabel: {
          //y轴文字的配置
          textStyle: {
            color: theme
          }
        },
        data: objs[i].map((value, index) => {
          //返回value
          return [isConversionUnits === 0 ? value : danweiHs(max, unit, value).val]
        })
      })
    }
  } else {
    for (let i of keys) {
      //循环折线图的数据
      let unit = zidian.unit_dict[i]
      list.push({
        //单位
        name: unit,
        axisLabel: {
          //y轴文字的配置
          textStyle: {
            color: theme
          }
        },
        data: []
      })
    }
  }
  let yA = {}
  list.forEach(item => {
    if (yA[item.name]) {
      yA[item.name].push(item.data)
    } else {
      yA[item.name] = [item.data]
    }
  })
  let yAxisArry = []
  for (let i in yA) {
    yA[i] = yA[i].flat(2).filter(item => item !== 'NaN')
    let minVal = Math.min(...yA[i].filter(item => item || item === 0))
    let maxVal = Math.max(...yA[i].filter(item => item || item === 0))
    if (minVal > 0) {
      minVal = minVal * 0.9
    } else if (minVal < 0) {
      minVal = minVal * 1.1
    }
    minVal = Math.floor(minVal * 100) / 100
    if (maxVal > 0) {
      maxVal = maxVal * 1.1
    } else if (maxVal < 0) {
      maxVal = maxVal * 0.9
    }
    maxVal = Math.ceil(maxVal * 100) / 100
    yAxisArry.push({
      type: 'value',
      name: i,
      position: yAxisArry.length % 2 ? 'right' : 'left',
      offset: yAxisArry.length * 20,
      // min:
      //   Math.min(...yA[i]) >= 0 ? 0 : -ceilNumber(Math.abs(Math.min(...yA[i]))),
      // max: Math.max(...yA[i]) < 0 ? 1 : ceilNumber(Math.max(...yA[i])),
      min: yAxisSource0 === 0 ? (minVal > 0 ? 0 : minVal) : minVal,
      max: yAxisSource0 === 0 ? (maxVal < 0 ? 0 : maxVal) : maxVal,
      axisLine: {
        show: true, // Y轴线
        lineStyle: {
          color: theme,
          type: 'solid'
        }
      },
      splitLine: {
        show: showYSplitLine,
        lineStyle: {
          type: 'dashed',
          color: 'rgba(255,255,255,.39)'
        }
      },
      axisTick: {
        show: true
      }
    })
  }
  return yAxisArry
  //生成多Y轴
}

export const Ycontent = (yAxis, newAxis) => {
  if (yAxis.length) {
    yAxis.forEach((item, index) => {
      item.max = newAxis[index].max > item.max ? newAxis[index].max : item.max
      item.min = newAxis[index].min < item.min ? newAxis[index].min : item.min
    })
  } else {
    yAxis = newAxis
  }
  return yAxis
}

const ceilNumber = number => {
  let bite = 0
  if (number < 10) {
    return 10
  }
  while (number >= 10) {
    number /= 10
    bite += 1
  }
  return Math.ceil(number) * Math.pow(10, bite)
}

export const timeSlot = (param, formatTime = 'yyyy-MM-dd HH:mm:ss', theme) => {
  let date = []
  if (param && param.date) {
    date = param.date
  } else {
    date = [`${format(new Date(), 'yyyy-MM-dd')} 00:00:00`, `${format(new Date(), 'yyyy-MM-dd')} 23:59:59`]
  }
  // param.data
  //X轴坐标
  let step = Difference(date) //间隔秒
  return timeEache(date, step, formatTime, theme)
}

const timeEache = (date, step, formatTime, theme) => {
  let data = [...date]
  let start = data[0] //时间
  let end = data[1] //时间戳
  return {
    type: 'time',
    // interval: '1', // 固定x轴时间间隔 间隔时间
    min: formatDate(start), // 开始时间时间戳
    max: formatDate(end), // 结束时间时间戳 如果实际的最大日期不确定，也可以不设定这个属性
    axisLabel: {
      formatter: value => {
        return format(formatDate(value), formatTime)
      },
      textStyle: {
        color: theme
      },
      interval: 100
      // showMinLabel: true, //是否显示最小 tick 的 label
      // showMaxLabel: true, //是否显示最大 tick 的 label
    },
    axisLine: {
      show: true,
      lineStyle: {
        color: theme,
        type: 'solid'
      }
    }
  }
}

const DuplicateData = (datas, Library) => {
  // 组合重复数据
  const zidian = Library.value
  let unitArray = {
    A: ['mA', 'A'],
    V: ['mV', 'V'],
    W: ['mW', 'W', 'kW', 'MW', 'GW'],
    WH: ['Wh', 'kWh', 'MWh', 'GWh'],
    分: ['分', '元', '万元', '十万', '百万', '千万', '亿', '十亿'],
    PA: ['Pa', 'kPa', 'MPa']
  }
  let newObject = {}
  for (let i in datas) {
    let unit = zidian.unit_dict[i.toUpperCase()] //从字典里便获取到的单位
    let start
    let key2
    for (let key in unitArray) {
      start = unitArray[key].includes(unit) //判断单位是否存在
      if (start) {
        key2 = key
        break
      }
    }
    if (start) {
      if (newObject[key2]) {
        //如果新值存在则往里边插入
        newObject[key2].push({
          [i]: datas[i]
        })
      } else {
        //如果不存在则
        newObject[key2] = []
        newObject[key2].push({
          [i]: datas[i]
        })
      }
    } else {
      newObject[unit] = [
        {
          [i]: datas[i]
        }
      ]
    }
  }
  return newObject
}

const maxFunc = afterObject => {
  // 求最大值和字段集合
  // afterObject组合完成之后的值
  let maxVal = []
  for (let i in afterObject) {
    let zh = ['A', 'V', 'W', 'WH', '分', 'PA'].includes(i) //如果它在这个里边，则是二维数组
    if (zh) {
      //这里救赎处理相同的
      let unitArray = []
      let zh = {
        unit: [],
        max: ''
      }
      for (let key in afterObject[i]) {
        for (let item in afterObject[i][key]) {
          //这个item是具体单位
          zh.unit.push(item)
          unitArray.push(afterObject[i][key][item]) //这一步是为了合并数组
        }
      }
      let oneArray = unitArray.flat() //转换完成的数组
      let Mathabs = oneArray.map(item => (item || item === 0 ? Math.abs(item) : 0)) //转换绝对值
      zh.max = Math.max(...Mathabs)
      maxVal.push(zh)
    }
  }
  return maxVal
}
